﻿using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace Devonline.Core;

public static class EnumExtensions
{
    /// <summary>
    /// 获取枚举类型的可显示名字
    /// </summary>
    /// <param name="enum">枚举值</param>
    /// <param name="type">枚举类型</param>
    /// <returns></returns>
    public static string? GetDisplayName(this Enum @enum)
    {
        var field = @enum.GetType().GetField(@enum.ToString("F"));
        if (field == null)
        {
            return string.Empty;
        }

        var display = field.GetCustomAttribute<DisplayAttribute>();
        if (display != null)
        {
            return display.Name;
        }

        var displayName = field.GetCustomAttribute<DisplayNameAttribute>();
        if (displayName != null)
        {
            return displayName.DisplayName;
        }

        var description = field.GetCustomAttribute<DescriptionAttribute>();
        if (description != null)
        {
            return description.Description;
        }

        return string.Empty;
    }
    /// <summary>
    /// 从枚举的 DisplayName 属性得到当前枚举值
    /// 用于从 excel 文本中反射获取枚举值
    /// </summary>
    /// <typeparam name="T">枚举类型</typeparam>
    /// <param name="value">DisplayName 的值</param>
    /// <returns>枚举值</returns>
    public static T GetEnumValueByDisplayName<T>(this string value) where T : struct, Enum
    {
        var type = typeof(T);
        return Enum.GetValues<T>().FirstOrDefault(x => type.GetDisplayName(x.ToString()) == value);
    }
    /// <summary>
    /// 从枚举的 DisplayName 属性得到当前枚举值
    /// 用于从 excel 文本中反射获取枚举值
    /// </summary>
    /// <param name="type">当前枚举</param>
    /// <param name="value">DisplayName 的值</param>
    /// <returns>枚举值</returns>
    public static object? GetEnumValueByDisplayName(this string value, Type type)
    {
        var values = Enum.GetValues(type);
        foreach (var item in values)
        {
            if (((Enum)item).GetDisplayName() == value)
            {
                return item;
            }
        }

        return null;
    }
    /// <summary>
    /// 通过枚举字段获取枚举对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static T GetEnumValueByJsonName<T>(this string value) where T : struct, Enum
    {
        var type = typeof(T);
        return Enum.GetValues<T>().FirstOrDefault(x => type.GetJsonPropertyName(x.ToString()) == value);
    }

    /// <summary>
    /// 将枚举转换为枚举值和显示值的键值对的默认形式
    /// 键采用 F 格式, 值采用可显示特性值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static ICollection<KeyValuePair<string, string?>> ToKeyValuePairs<T>() where T : struct, Enum => Enum.GetValues<T>().ToDictionary(key => key.ToString("F"), value => value.GetDisplayName());
    /// <summary>
    /// 将枚举转换为键值可定义的键值对
    /// F 格式将显示枚举的字符串表示值
    /// D 格式将显示枚举的数字表示值
    /// 值格式不传值则默认使用可显示特性描述值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static ICollection<KeyValuePair<string, string?>> ToKeyValuePairs<T>(string keyFormat = "F", string? valueFormat = null) where T : struct, Enum => Enum.GetValues<T>().ToDictionary(key => key.ToString(keyFormat), value => string.IsNullOrWhiteSpace(valueFormat) ? value.GetDisplayName() : value.ToString(valueFormat));
}